package cn.lysj.framework.common.utils.websocket;


import cn.lysj.framework.common.utils.json.GsonUtil;
import cn.lysj.framework.common.utils.web.ParamUtil;
import cn.lysj.framework.common.utils.web.Resp;
import cn.lysj.framework.customer.domain.Customer;
import cn.lysj.framework.customer.service.CustomerService;
import cn.lysj.framework.store.domain.CustEatTable;
import cn.lysj.framework.store.service.CustEatTableService;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @Author: ZhangWenJian
 * @Create: 2018/7/21--16:17
 * @Description: WebSocket服务类
 */



@ServerEndpoint(value = "/websocket/{sid}")
@Component
public class WebSocketServerToUser {
    ApplicationContext act = ApplicationContextRegister.getApplicationContext();

    private  final static Logger log = LoggerFactory.getLogger(WebSocketServerToUser.class);
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServerToUser> webSocketSet = new CopyOnWriteArraySet<WebSocketServerToUser>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    //接收sid
    private String sid="";
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
        this.sid=sid;
    }



    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        String[] sids = this.sid.split("-");
        disposeCustEatTable(sids[1],sids[0]);
        //此步骤需要异常处理
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭！"+"拼桌Id"+sids[0]+"用户id"+sids[1]+"当前在线人数为" + getOnlineCount());
    }

    /**
     * @author ZhangWenJian
     * @date 2019/2/20 8:53
     * @title disposeCustEatTable
     * @param customerId
     * @param custEatTableId
     * @return void
     * @description 用户离开桌子操作
     */
    public void disposeCustEatTable(String customerId,String custEatTableId){
        //调用service类
        CustEatTableService custEatTableService = act.getBean(CustEatTableService.class);

        CustEatTable custEatTable = custEatTableService.getRepository().findOne(custEatTableId);
        custEatTable.setUpdateTime(new Date());
        custEatTableService.save(custEatTable);
        String[] objectIds = custEatTable.getInitiatorId().split("-");
        for (int i = objectIds.length-1; i>=0 ;i--){
            if(objectIds[i].equals(customerId)){
                objectIds = (String[]) ArrayUtils.remove(objectIds,i);
                break;
            }
        }
        String msg = "该桌子还在拼桌!";
        if(objectIds.length == 0){
            msg = "由于拼桌人数为0,该拼桌已经结束!";
            custEatTable.setStatus(2);
        }
        String objectIdList = "";
        for (int i = 0; i<objectIds.length ;i++){
            if(ParamUtil.isBlank(objectIdList)){
                objectIdList += objectIds[i];
            }
            else {
                objectIdList += "-"+objectIds[i];
            }
        }
        custEatTable.setInitiatorId(objectIdList);
        custEatTableService.getRepository().save(custEatTable);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到来自窗口"+sid+"的信息:"+message);
        //群发消息
        for (WebSocketServerToUser item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    //给对象发送获取食品列表请求
    public static Boolean getFoodListRequest(CustEatTable custEatTable,String customerId,String custEatTableId){
        String[] initiatorIds = custEatTable.getInitiatorId().split("-");
        Boolean type = false;
        for (String initiatorId:initiatorIds){
            if(type == false){
                for (WebSocketServerToUser item : webSocketSet) {
                    try {
                        if(item.sid.equals(custEatTableId+"-"+initiatorId) && !initiatorId.equals(customerId)){
                            WebSocketObj webSocketObj = new WebSocketObj();
                            webSocketObj.setIncidentType(IncidentType.SEND_FOOD_LIST);
                            webSocketObj.setData(customerId);
                            item.sendMessage(GsonUtil.toJson(new Resp(webSocketObj)));
                            type = true;
                            break;
                        }
                    } catch (IOException e) {
                        continue;
                    }
                }
            }
        }
        return type;
    }



    //给指定对象发送数据 1.服务类型 2.数据 3.对象
    public static Boolean sendDataToOnePeople(Integer incidentType,Object data,Object objectId,String jointId){
        boolean type = false;
        for (WebSocketServerToUser item : webSocketSet) {
            try {
                if(item.sid.equals(jointId+"-"+objectId)){
                    WebSocketObj webSocketObj = new WebSocketObj();
                    webSocketObj.setIncidentType(incidentType);
                    webSocketObj.setData(data);
                    item.sendMessage(GsonUtil.toJson(new Resp(webSocketObj)));
                    type = true;
                    break;
                }
            } catch (IOException e) {
                continue;
            }
        }
        return type;
    }

    //给指定对象集合其中一个发送数据 1.服务类型 2.数据 3.对象
    public static Integer sendDataToMorePeopleArray(Integer incidentType,Object data,Object[] objectIds,String jointId){
        Integer peopleNum = 0;
        for(Object objectId:objectIds){
            for (WebSocketServerToUser item : webSocketSet) {
                try {
                    if(item.sid.equals(jointId+"-"+objectId)){
                        WebSocketObj webSocketObj = new WebSocketObj();
                        webSocketObj.setIncidentType(incidentType);
                        webSocketObj.setData(data);
                        item.sendMessage(GsonUtil.toJson(new Resp(webSocketObj)));
                        peopleNum += 1;
                        break;
                    }
                } catch (IOException e) {
                    continue;
                }
            }
        }
        return peopleNum;
    }



    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServerToUser.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServerToUser.onlineCount--;
    }

}
